<?php
define("SQLT_NUMBER",1);
define("SQLT_STRING",2);
define("SQLT_DATE",3);

class SQLCreator {
    /**
    $config=array(
        "tableName"=>array(
            "fn1"=>new SQLType(SQLT_NUMBER,true,true),
            "fn2"=>new SQLType(SQLT_STRING),
            "fn3"=>new SQLType(SQLT_STRING),
            "fn4"=>new SQLType(SQLT_STRING)
            
        ),
        "table2"=>array(...),
        ...
    );
    */
    public function __construct($config=null){
        $this->loadConfig($config);
    }
    
    protected static $_singlon;
    
    /**
     *@return SQLCreator SQLCreator单实例
    */
    public static function singlon(){
        $cfg=Config::load("datatable");
        if( !isset(self::$_singlon)){
            self::$_singlon=new SQLCreator($cfg->data);
        }
        return self::$_singlon;
    }
    
    protected $aliasIndex=1;
    
    public $config=null;
    
    public function loadConfig($config){
        $this->config=$config;
    }
    
    public function insert($tableName,$valList){
        $tableConfig=$this->config[$tableName];
        $values=array();
        $fields=array();
        foreach($valList as $fn=>$val){
            if(!array_key_exists($fn,$tableConfig)) continue;
            /**
             *@var SQLType
            */
            $type=$tableConfig[$fn];
            if($type->isAuto) continue;
            $values[]=$type->value($val);
            $fields[]=$fn;
        }
        $fl=implode(",",$fields);
        $vl=implode(",",$values);
        $sql="insert into {$tableName}({$fl}) values($vl)";
        
        return $sql;
    }
    public function update($tableName,$setList,$where=null){
        $tableConfig=$this->config[$tableName];
        $setVals=array();
        $whList=array();
        
        foreach($setList as $fn=>$val){
            if(!array_key_exists($fn,$tableConfig)) continue;
            /**
             *@var SQLType
            */
            $type=$tableConfig[$fn];
            if($type->isPrimary){
                $whList[]=$fn."=".$type->value($val);
                continue;
            }
            $setVals[]=$fn."=".$type->value($val);
        }
        if(!empty($where)){
            foreach($where as $fn=>$val){
                if(!array_key_exists($fn,$tableConfig)) continue;
                /**
                 *@var SQLType
                */
                $type=$tableConfig[$fn];
                $whList[]=$fn."=".$type->value($val);
            }
        }
        $sql="update {$tableName} set ".implode(",",$setVals);
        if(!empty($whList)){
            $sql .= " where ".implode(" and ",$whList);
        }
        return $sql;
    }
    public function select($tableName,$where=null){
        $tableConfig=$this->config[$tableName];
        $fields=array_keys($tableConfig);
        $sql="select ".implode(",",$fields)." from {$tableName}";
        if(!empty($where)){
            $whList=array();
            foreach($where as $fn=>$val ){
                if(!array_key_exists($fn,$tableConfig)) continue;
                /**
                 *@var SQLType
                */
                $type=$tableConfig[$fn];
                $whList[]=$fn."=".$type->value($val);
            }
            $sql .= " where ".implode(" and ",$whList);
        }
        return $sql;
    }
    /**
     * @param array $name Description
     */
    public function delete($tableName,$where=null){
        $tableConfig=$this->config[$tableName];
        $fields=array_keys($tableConfig);
        $sql="delete from {$tableName}";
        if(!empty($where)){
            $whList=array();
            foreach($where as $fn=>$val ){
                if(!array_key_exists($fn,$tableConfig)) continue;
                /**
                 *@var SQLType
                */
                $type=$tableConfig[$fn];
                $whList[]=$fn."=".$type->value($val);
            }
            $sql .= " where ".implode(" and ",$whList);
        }
        return $sql;
    }
    
    /**
     * 从$data中筛选出属于$tableName中的字段集合
     * $data应为一行数据
     */
    public function fetchFields($tableName,$data){
        if(!array_key_exists($tableName,$this->config)){
            return array();
        }
        $config=$this->config[$tableName];
        $fields=array();
        foreach($config as $fn=>$type){
            if(array_key_exists($fn,$data)){
                $fields[]=$fn;
            }
        }
        return $fields;
    }
    
    
    /**
     * 从$data中筛选出属于$tableName中的字段数据，并进行数据处理
     * $data应为一行数据
     */
    public function fetchValues($tableName,$data){
        if(!array_key_exists($tableName,$this->config)){
            return array();
        }
        $config=$this->config[$tableName];
        $values=array();
        foreach($config as $fn=>$type){
            if(array_key_exists($fn,$data)){
                $values[$fn]=$type->value($data[$fn]);
            }
        }
        return $values;
    }
}

class SQLType {
    public function __construct($dataType,$isPrimary=false,$isAuto=false){
        $this->dataType=$dataType;
        $this->isPrimary=$isPrimary;
        $this->isAuto=$isAuto;
    }
    public $dataType;
    public $isPrimary;
    public $isAuto;
    
    public function value($val){
        return self::SQLVal($val,$this->dataType);
    }
    
    public static function SQLVal($val,$type){
        switch($type){
            case SQLT_NUMBER:
                return self::NumVal($val);
                break;
            case SQLT_STRING:
                return self::StrVal($val);
                break;
            case SQLT_DATE:
                return self::DateVal($val);
                break;
        }
        return "null";
    }
    public static function NumVal($val){
        if( is_numeric($val) ){
            return $val;
        }
        return "null";
    }
    public static function StrVal($val){
        if(empty($val)){
            return "null";
        }
        return "'".str_replace("'","''",$val)."'";
    }
    public static function DateVal($val){
        return self::StrVal($val);
    }
}
